1 00:00:00,740 --> 00:00:01,400 Okay. 2 00:00:01,400 --> 00:00:05,840 In this lecture we're going to take a look at creating a basic admin system. 3 00:00:05,840 --> 00:00:10,760 This admin system features an on screen command line that you can bring up, pressing the semicolon 4 00:00:10,760 --> 00:00:13,700 button, and you can enter in any commands you'd like in here. 5 00:00:13,700 --> 00:00:16,520 And we're also going to add chat support for commands as well. 6 00:00:16,520 --> 00:00:21,380 So I can use a command such as speed me and set a number like 100. 7 00:00:21,380 --> 00:00:26,330 And then I increase my speed and then I can do some other wacky commands like killing myself. 8 00:00:26,330 --> 00:00:28,970 So kill me and it kills the character. 9 00:00:28,970 --> 00:00:32,510 And of course we can do the exact same commands in the command line as well. 10 00:00:32,510 --> 00:00:37,880 If we hit a colon, we can see all of the commands that are available to us, and we can fill out any 11 00:00:37,880 --> 00:00:44,000 of these things, such as flinging ourselves so we can do fling me and it'll fling us far away. 12 00:00:44,690 --> 00:00:50,300 Our admin system also features an on screen messaging system to let the user know whoever is using commands, 13 00:00:50,300 --> 00:00:52,040 whether or not they made a mistake. 14 00:00:52,040 --> 00:00:59,240 So, for example, if I wanted to set my speed and I don't enter in a number, let's say I enter in 15 00:00:59,240 --> 00:01:04,700 a random string like that, it's going to give me an error and it's going to tell me command speed expected 16 00:01:04,700 --> 00:01:08,840 number for argument number two got string instead, and we can hit okay. 17 00:01:08,840 --> 00:01:11,660 And now we'll know to fix our command. 18 00:01:14,930 --> 00:01:19,430 To get started, I've attached a model to the lecture you're going to want to grab and insert into your 19 00:01:19,430 --> 00:01:19,970 game. 20 00:01:19,970 --> 00:01:25,340 Inside of this model, we have a couple things we need to put in some services we have a folder of all 21 00:01:25,340 --> 00:01:33,260 the assets we'll need for our admin system, including some bind tables, a bindable function, a remote 22 00:01:33,260 --> 00:01:38,510 function, as well as a remote event, as well as some other module scripts to store the commands for 23 00:01:38,510 --> 00:01:45,740 our admin, storing some of the settings for the admin and one module script to act as an enum for our 24 00:01:45,740 --> 00:01:46,700 admin system. 25 00:01:46,700 --> 00:01:52,670 So you can go ahead and take first the server script to handle our admin system and put that inside 26 00:01:52,670 --> 00:01:54,200 of server script service. 27 00:01:54,200 --> 00:01:58,850 And we can go ahead and take this folder and place it inside of replicated storage. 28 00:01:59,700 --> 00:02:02,550 And in here we can go ahead and take a look at some of the module scripts. 29 00:02:02,550 --> 00:02:10,290 So for admin enum we just have a couple key value pairs in here to represent different values for administrators. 30 00:02:10,290 --> 00:02:13,500 So anybody who's a non admin will have a rank of zero. 31 00:02:13,500 --> 00:02:19,350 Moderators have a rank of ten admin a rank of 20 and owners 250. 32 00:02:19,350 --> 00:02:24,000 So these numbers just represent, you know, different levels to set for commands. 33 00:02:24,420 --> 00:02:29,730 And then of course we also have a module script to store some settings such as what prefix we want to 34 00:02:29,730 --> 00:02:30,660 use for the command. 35 00:02:30,660 --> 00:02:33,330 So we could change it from a colon to an exclamation mark. 36 00:02:33,330 --> 00:02:36,480 We could do a semicolon, but I'll just do a colon for now. 37 00:02:36,480 --> 00:02:41,400 And then in here we can store all of the hard coded players we want to have admin in our game. 38 00:02:41,400 --> 00:02:44,310 So for example here this is my players ID. 39 00:02:44,310 --> 00:02:49,350 And I've hard coded it to set myself to be the owner for this admin system. 40 00:02:49,350 --> 00:02:56,220 And then we have a couple other tables to keep track of temporary mods or server mods and server bans. 41 00:02:56,220 --> 00:02:59,010 So if we want to ban anybody we'll storm in here. 42 00:02:59,010 --> 00:03:00,990 And kick them if they're in this table. 43 00:03:01,320 --> 00:03:02,430 One more thing we want to set up. 44 00:03:02,430 --> 00:03:05,400 We want to go into our command module script. 45 00:03:05,400 --> 00:03:09,120 And in here we're going to store a table that contains all of the commands. 46 00:03:09,120 --> 00:03:11,340 And we can actually set this up real quick. 47 00:03:11,340 --> 00:03:14,040 So I want to just have two services in here. 48 00:03:14,040 --> 00:03:16,260 One is going to be the run service. 49 00:03:19,050 --> 00:03:22,410 And then we're just going to, of course, need replicated storage. 50 00:03:27,960 --> 00:03:31,980 And then from this point I want to create a boolean I'll call it is server. 51 00:03:31,980 --> 00:03:36,660 And we're going to use the run service to check whether or not this module script is running on the 52 00:03:36,660 --> 00:03:38,430 client or on the server. 53 00:03:38,430 --> 00:03:43,110 And that's because I'm going to have this module script required by both the client and the server. 54 00:03:43,110 --> 00:03:48,270 That way the client can see what commands they have access to, and that way the server can require 55 00:03:48,270 --> 00:03:53,400 it as well and execute all of the server functionality for different commands. 56 00:03:53,400 --> 00:03:58,740 So if we're on the server, then I just want to create some variables specific to the server. 57 00:03:58,740 --> 00:04:01,350 So one I'll call coms Bindable. 58 00:04:01,350 --> 00:04:05,880 And I'm not going to make it local here because I want it to be available to the entire script. 59 00:04:05,880 --> 00:04:08,760 If I made it local, it would be confined to this if statement. 60 00:04:08,760 --> 00:04:09,930 So I don't want to do that. 61 00:04:09,930 --> 00:04:16,860 So we're going to get inside of replicated storage, our admin assets and get our communication bindable. 62 00:04:16,860 --> 00:04:20,730 And this is for communication between different server scripts. 63 00:04:20,730 --> 00:04:23,520 We're going to have one Coms event. 64 00:04:23,610 --> 00:04:27,990 And this is going to be for communication between the client and the server. 65 00:04:27,990 --> 00:04:32,400 And then we're going to require the admin settings module script. 66 00:04:32,400 --> 00:04:36,810 So replicated storage admin assets and get the settings module script. 67 00:04:36,810 --> 00:04:39,090 And we're going to go ahead and require this. 68 00:04:42,540 --> 00:04:42,990 Otherwise. 69 00:04:42,990 --> 00:04:47,610 I also want to require the admin enum, and we can do this on both the client and the server. 70 00:04:47,610 --> 00:04:51,120 So require script dot parent. 71 00:04:51,970 --> 00:04:54,160 And we could just do admin enum. 72 00:04:54,160 --> 00:05:00,670 This shouldn't be an issue for the client, but if you'd like you could go ahead and use wait for child, 73 00:05:00,670 --> 00:05:02,470 but I don't think it's necessary. 74 00:05:03,420 --> 00:05:05,580 And then I'm going to use RNG. 75 00:05:05,610 --> 00:05:08,610 So we're going to create a new random data type. 76 00:05:08,610 --> 00:05:11,400 And we're going to use that later for different commands. 77 00:05:12,350 --> 00:05:17,900 Now inside of here, I just want to have one private function and that's for checking arguments passed 78 00:05:17,900 --> 00:05:19,760 to functions checking their type. 79 00:05:19,760 --> 00:05:21,470 So again we'll do check arg. 80 00:05:22,610 --> 00:05:23,810 For type. 81 00:05:23,840 --> 00:05:27,830 We will take an argument and we want to check the type. 82 00:05:27,830 --> 00:05:30,560 So we'll call it expected type and set it to a string. 83 00:05:30,740 --> 00:05:36,200 Now when this function gets called of course we first want to make sure that we didn't pass nil to the 84 00:05:36,200 --> 00:05:38,600 second parameter so we could assert. 85 00:05:39,410 --> 00:05:40,340 Expected type. 86 00:05:40,340 --> 00:05:49,130 If it's nil or false, then we're going to send a message like check arg or type requires string for 87 00:05:49,130 --> 00:05:50,750 expected type. 88 00:05:51,540 --> 00:05:54,780 But we got no we could just say got no. 89 00:05:57,090 --> 00:06:03,930 Another thing we want to check is if the type of expected type is not equal to a string, because we 90 00:06:03,930 --> 00:06:04,770 want a string here. 91 00:06:04,770 --> 00:06:09,840 But if for some reason whoever is scripting in here didn't pass a string, we want to let them know 92 00:06:09,840 --> 00:06:21,480 so we can error and we could say something like check arg for type requires string for expected type 93 00:06:21,660 --> 00:06:24,510 and we got whatever instead. 94 00:06:24,510 --> 00:06:26,460 So we're going to put a directive in here. 95 00:06:26,460 --> 00:06:29,610 And then we're going to use the format function. 96 00:06:29,610 --> 00:06:32,130 And what do we want to replace at that directive. 97 00:06:32,130 --> 00:06:36,240 Well we can get the string of the type expected type. 98 00:06:36,240 --> 00:06:39,000 So it could be like a number a boolean whatever. 99 00:06:39,000 --> 00:06:40,230 They didn't pass a string. 100 00:06:40,230 --> 00:06:42,360 So we're going to error and let them know. 101 00:06:42,360 --> 00:06:45,840 Otherwise we're going to use some syntax magic here. 102 00:06:45,840 --> 00:06:48,450 And I'm going to put a return statement. 103 00:06:48,450 --> 00:06:51,510 And inside this return statement I'm going to put an if statement. 104 00:06:51,510 --> 00:07:01,740 So if the type of our argument is equal to the expected type, or let's say the type of our argument 105 00:07:01,740 --> 00:07:03,090 is an instance. 106 00:07:03,090 --> 00:07:05,370 So we want to check the class of this instance. 107 00:07:05,370 --> 00:07:11,370 So and arg is a and we'll pass the expected type here. 108 00:07:12,370 --> 00:07:19,000 So if it's either the expected type or it's an instance and belongs to the class we expect, then we're 109 00:07:19,000 --> 00:07:20,440 going to put true here. 110 00:07:20,440 --> 00:07:24,940 So that means if this if statement evaluates to true it's going to return true. 111 00:07:25,550 --> 00:07:30,020 Otherwise we can put else and then just put false here. 112 00:07:30,020 --> 00:07:35,090 So what this is doing is it's evaluating whether or not this is going to be true or false. 113 00:07:35,090 --> 00:07:39,200 If the condition is true and the if statement, it's going to return true, otherwise it's going to 114 00:07:39,200 --> 00:07:40,190 return false. 115 00:07:40,190 --> 00:07:40,850 And guess what. 116 00:07:40,850 --> 00:07:42,920 We don't have to put an end statement here. 117 00:07:43,830 --> 00:07:47,310 So that's a little bit of some syntactical magic here in Lua. 118 00:07:48,090 --> 00:07:53,400 Now let's go ahead and go into our current commands table, because in here I want to create some or 119 00:07:53,400 --> 00:07:55,620 I'll just create an example key value pair. 120 00:07:55,620 --> 00:08:00,300 So we'll put a key here as a string and we'll just do example. 121 00:08:00,300 --> 00:08:02,430 So this will be our example command. 122 00:08:03,180 --> 00:08:07,440 And what I want to store in this command is first I want to give a name to our command. 123 00:08:07,440 --> 00:08:09,090 So what's the name of our command? 124 00:08:09,090 --> 00:08:11,130 I'm just going to put example here for now. 125 00:08:11,520 --> 00:08:15,540 The next thing we want is we want to define the minimum rank for this command. 126 00:08:15,540 --> 00:08:19,770 So what players or what administrators in our game can use this command. 127 00:08:19,770 --> 00:08:21,390 So we could do minimum. 128 00:08:21,390 --> 00:08:25,980 Minimum rank is equal to and we can use our admin enum. 129 00:08:25,980 --> 00:08:27,210 So admin enum. 130 00:08:27,420 --> 00:08:30,600 And for now we could just set it to like moderator. 131 00:08:32,310 --> 00:08:35,910 Uh, we can define the usage for this command. 132 00:08:35,910 --> 00:08:43,590 So for example, maybe a player could type like colon kill or they could also do like colon. 133 00:08:43,590 --> 00:08:45,420 Uh, oops. 134 00:08:45,420 --> 00:08:46,170 Death. 135 00:08:46,170 --> 00:08:49,230 You know, we want to give them multiple options for this command. 136 00:08:49,620 --> 00:08:53,100 So for now I'll just do example and then example two. 137 00:08:53,100 --> 00:08:55,380 And we don't need to put the colon in here. 138 00:08:55,380 --> 00:09:02,010 We'll add that in later because I want to be able to change the prefix only from the script alone. 139 00:09:02,010 --> 00:09:07,140 And I don't want it to have to go into each command and change each semicolon by itself. 140 00:09:07,140 --> 00:09:08,520 That'd be a little redundant. 141 00:09:08,700 --> 00:09:13,860 The next thing we need to define is the required parameters for this command. 142 00:09:13,860 --> 00:09:17,250 So as you know, different commands are going to have different parameters. 143 00:09:17,250 --> 00:09:23,340 Some will require a player, some will require a number or multiple different parameters. 144 00:09:23,340 --> 00:09:27,840 So we'll have a table that stores all of the parameters for this command in order. 145 00:09:27,840 --> 00:09:30,690 And we'll declare the type of those parameters here. 146 00:09:30,690 --> 00:09:34,650 So for example, maybe the first parameter needs to be of the type player. 147 00:09:34,650 --> 00:09:37,680 And maybe the second parameter needs to be of the type number. 148 00:09:37,680 --> 00:09:42,030 And then the last thing we'll need inside of this function I'm going to call it callback. 149 00:09:42,030 --> 00:09:45,480 And that means we're going to be calling back a function. 150 00:09:45,480 --> 00:09:47,820 So there's going to be a function stored here. 151 00:09:47,820 --> 00:09:51,660 And this function is going to execute all of the functionality for this command. 152 00:09:51,660 --> 00:09:54,360 And in here this is where you would define the parameters. 153 00:09:54,360 --> 00:10:01,020 So like clam one would be our player and param two would be our number. 154 00:10:01,260 --> 00:10:05,820 And then when we would execute according to those parameters and whatever the command is. 155 00:10:05,940 --> 00:10:12,360 And then at the very end, uh, to make sure that everything went smoothly, we can return true. 156 00:10:12,510 --> 00:10:18,690 Otherwise, if something goes wrong in this function, we could return false and give them an error 157 00:10:18,690 --> 00:10:22,740 message like something wrong happened or something like that. 158 00:10:22,950 --> 00:10:25,560 And we can make sure to denote that using type annotation. 159 00:10:25,560 --> 00:10:28,830 So we could say that this returns a boolean. 160 00:10:29,760 --> 00:10:33,000 And it could also possibly return a string. 161 00:10:33,000 --> 00:10:38,040 So we'll put a question mark there, because if it returns true then it's not going to return a string. 162 00:10:38,740 --> 00:10:39,280 Alrighty. 163 00:10:39,280 --> 00:10:43,900 So now that we've got everything set up in the next lecture, we're going to go ahead and start scripting 164 00:10:43,900 --> 00:10:44,860 on the server. 165 00:10:44,860 --> 00:10:46,810 So I'll go ahead and see you there.